/*
 * Copyright (c) 2023 iQi.Co.Ltd. All rights reserved.
 */
 
using System.Collections.Generic;
using NetProtocol.POD;
using NetProtocol.Enum;
using IQIGame.Onigao.Game;
using IQIGame.Onigao.GamePlay;
using IQIGame.Onigao.Framework;
using System.Threading.Tasks;
using System;

namespace NetProtocol.Server {
	/// <summary>
	/// 道具模块
	/// module : item
	/// </summary>
	public interface SNetItem : INetServerModule {
		Dictionary<int, MessageHandler> INetServerModule.GetModuleFunction()
        {	
            return new()
            {
                { NetMessageId.item_sellItem, (session, data) =>
		            {
#if ENABLE_NET_LOG || UNITY_EDITOR
						NetProtocolHelper.ServerLog(NetMessageId.item_sellItem, "Recv->" + data.ToString());
#endif
		                SellItemRequest _data = (SellItemRequest)data;
						return CS_sellItem(session, _data.itemIds, _data.basicItems);
		            } 
            	},
                { NetMessageId.item_useItem, (session, data) =>
		            {
#if ENABLE_NET_LOG || UNITY_EDITOR
						NetProtocolHelper.ServerLog(NetMessageId.item_useItem, "Recv->" + data.ToString());
#endif
		                UseItemRequest _data = (UseItemRequest)data;
						return CS_useItem(session, _data.request);
		            } 
            	},
                { NetMessageId.item_exchange, (session, data) =>
		            {
#if ENABLE_NET_LOG || UNITY_EDITOR
						NetProtocolHelper.ServerLog(NetMessageId.item_exchange, "Recv->" + data.ToString());
#endif
		                ExchangeRequest _data = (ExchangeRequest)data;
						return CS_exchange(session, _data.cid, _data.count);
		            } 
            	},
                { NetMessageId.item_exchangeBatch, (session, data) =>
		            {
#if ENABLE_NET_LOG || UNITY_EDITOR
						NetProtocolHelper.ServerLog(NetMessageId.item_exchangeBatch, "Recv->" + data.ToString());
#endif
		                ExchangeBatchRequest _data = (ExchangeBatchRequest)data;
						return CS_exchangeBatch(session, _data.idCounts);
		            } 
            	},
                { NetMessageId.item_setPortableItem, (session, data) =>
		            {
#if ENABLE_NET_LOG || UNITY_EDITOR
						NetProtocolHelper.ServerLog(NetMessageId.item_setPortableItem, "Recv->" + data.ToString());
#endif
		                SetPortableItemRequest _data = (SetPortableItemRequest)data;
						return CS_setPortableItem(session, _data.itemId);
		            } 
            	},
            };
        }
        
        Dictionary<int, Func<IReceiveMessage>> INetServerModule.GetModuleRequest() 
        {
	        return new ()
	        {
	        	{NetMessageId.item_sellItem, ()=> new SellItemRequest()},
	        	{NetMessageId.item_useItem, ()=> new UseItemRequest()},
	        	{NetMessageId.item_exchange, ()=> new ExchangeRequest()},
	        	{NetMessageId.item_exchangeBatch, ()=> new ExchangeBatchRequest()},
	        	{NetMessageId.item_setPortableItem, ()=> new SetPortableItemRequest()},
	        };
	    }
        
#region Server-side Interface
		/// <summary>
        ///  出售道具
        /// </summary>
	    protected SellItemResult CS_sellItem(ISession session, List<long> itemIds, Dictionary<int, int> basicItems);
		/// <summary>
        ///  使用道具
        /// </summary>
	    protected UseItemResult CS_useItem(ISession session, UseItemRequestPOD request);
		/// <summary>
        ///  兑换
        /// </summary>
	    protected ExchangeResult CS_exchange(ISession session, int cid, int count);
		/// <summary>
        ///  批量兑换idCounts(key=cid,value=count)
        /// </summary>
	    protected ExchangeBatchResult CS_exchangeBatch(ISession session, Dictionary<int, int> idCounts);
		/// <summary>
        ///  设置快捷道具，0表示卸下，int值表示cid，long值表示唯一id
        /// </summary>
	    protected SetPortableItemResult CS_setPortableItem(ISession session, long itemId);
#endregion
#region Client-side Interface
		/// <summary>
        /// 
        /// </summary>
        public SellItemResult SC_sellItemResult(Task<SellItemResult> future){return new SellItemResult(future);}
        public SellItemResult SC_sellItemResult(int code){return new SellItemResult(code);}
		/// <summary>
        /// addItems=获得的道具
        /// </summary>
        public UseItemResult SC_useItemResult(Task<UseItemResult> future){return new UseItemResult(future);}
        public UseItemResult SC_useItemResult(int code, UseItemResultPOD result){return new UseItemResult(code, result);}
        public UseItemResult SC_useItemResult(int code){return new UseItemResult(code);}
		/// <summary>
        /// success=是否成功，showItems=展示物品, exchangeRecords=兑换记录,key=cid，value=次数, 暴击倍数
        /// </summary>
        public ExchangeResult SC_exchangeResult(Task<ExchangeResult> future){return new ExchangeResult(future);}
        public ExchangeResult SC_exchangeResult(int code, bool success, List<ItemShowPOD> showItems, Dictionary<int, int> exchangeRecords, float critMultiple){return new ExchangeResult(code, success, showItems, exchangeRecords, critMultiple);}
        public ExchangeResult SC_exchangeResult(int code){return new ExchangeResult(code);}
		/// <summary>
        /// showItems=展示物品, exchangeRecords=兑换记录,key=cid，value=次数
        /// </summary>
        public ExchangeBatchResult SC_exchangeBatchResult(Task<ExchangeBatchResult> future){return new ExchangeBatchResult(future);}
        public ExchangeBatchResult SC_exchangeBatchResult(int code, Dictionary<int, int> successInfo, List<ItemShowPOD> showItems, Dictionary<int, int> exchangeRecords){return new ExchangeBatchResult(code, successInfo, showItems, exchangeRecords);}
        public ExchangeBatchResult SC_exchangeBatchResult(int code){return new ExchangeBatchResult(code);}
		/// <summary>
        ///  提示用，不更新数据
        /// </summary>
        public SetPortableItemResult SC_setPortableItemResult(Task<SetPortableItemResult> future){return new SetPortableItemResult(future);}
        public SetPortableItemResult SC_setPortableItemResult(int code){return new SetPortableItemResult(code);}
		/// <summary>
        ///  当客户端不知道明确操作目标的时候(道具)变动的数据通知
        /// </summary>
		public bool SC_notifyItemChange(ISession session, List<ItemPOD> updateList){
	        return NetProtocolHelper.SendMessage(session, new NotifyItemChange(updateList));
	    }
	    public void SC_notifyItemChange_Broadcast(List<ISession> sessions, List<ItemPOD> updateList){
	        NetProtocolHelper.BroadcastMessage(sessions, new NotifyItemChange(updateList));
	    }
		/// <summary>
        ///  当客户端不知道明确操作目标的时候(道具)移除的数据通知
        /// </summary>
		public bool SC_notifyItemRemove(ISession session, List<long> removeList){
	        return NetProtocolHelper.SendMessage(session, new NotifyItemRemove(removeList));
	    }
	    public void SC_notifyItemRemove_Broadcast(List<ISession> sessions, List<long> removeList){
	        NetProtocolHelper.BroadcastMessage(sessions, new NotifyItemRemove(removeList));
	    }
		/// <summary>
        ///  当客户端不知道明确操作目标的时候(道具)变动的数据通知 -- num为0不删除，货币默认0
        /// </summary>
		public bool SC_notifyBasicItemChange(ISession session, Dictionary<int, int> updateList){
	        return NetProtocolHelper.SendMessage(session, new NotifyBasicItemChange(updateList));
	    }
	    public void SC_notifyBasicItemChange_Broadcast(List<ISession> sessions, Dictionary<int, int> updateList){
	        NetProtocolHelper.BroadcastMessage(sessions, new NotifyBasicItemChange(updateList));
	    }
		/// <summary>
        ///  更新玩家道具欠债，全量更新 -- num为0可删
        /// </summary>
		public bool SC_notifyItemDebts(ISession session, Dictionary<int, int> itemDebts){
	        return NetProtocolHelper.SendMessage(session, new NotifyItemDebts(itemDebts));
	    }
	    public void SC_notifyItemDebts_Broadcast(List<ISession> sessions, Dictionary<int, int> itemDebts){
	        NetProtocolHelper.BroadcastMessage(sessions, new NotifyItemDebts(itemDebts));
	    }
		/// <summary>
        ///  同步物品冷却信息，全量更新
        /// </summary>
		public bool SC_notifyItemCdInfo(ISession session, Dictionary<int, int> itemCdInfo){
	        return NetProtocolHelper.SendMessage(session, new NotifyItemCdInfo(itemCdInfo));
	    }
	    public void SC_notifyItemCdInfo_Broadcast(List<ISession> sessions, Dictionary<int, int> itemCdInfo){
	        NetProtocolHelper.BroadcastMessage(sessions, new NotifyItemCdInfo(itemCdInfo));
	    }
		/// <summary>
        ///  通知更新快捷道具
        /// </summary>
		public bool SC_notifyUpdatePortableItem(ISession session, long itemId){
	        return NetProtocolHelper.SendMessage(session, new NotifyUpdatePortableItem(itemId));
	    }
	    public void SC_notifyUpdatePortableItem_Broadcast(List<ISession> sessions, long itemId){
	        NetProtocolHelper.BroadcastMessage(sessions, new NotifyUpdatePortableItem(itemId));
	    }
#endregion

#region Messages
	public class SellItemResult : MessageResult {
	    public SellItemResult(Task<SellItemResult> future): base(future) { }
		public SellItemResult(int code): base(code) { }
		public new SellItemResult SetDelayCall(Action delayCall) { base.SetDelayCall(delayCall); return this; }
        public override MessageResult GetFutureResult(Task task) { return ((Task<SellItemResult>)task).Result; }
		public override int GetMessageId() {return NetMessageId.item_sellItemResult;}
		public override SendPackage ToPackage() {
			SendPackage si_p = NetProtocolHelper.GetSendPackage();
			si_p.Header.Messagid = NetMessageId.item_sellItemResult;
			si_p.StartWrite();
			SOutputStream _out = si_p.OutputStream;
			_out.Write_int(code);
			return si_p;
		}
		public override string ToString() {
    		return "Item.SC_sellItemResult { "
			+ "code="
			+ code
			+" }";
		}
	}
	public class UseItemResult : MessageResult {
	    private UseItemResultPOD result;
	    public UseItemResult(Task<UseItemResult> future): base(future) { }
		public UseItemResult(int code): base(code) { }
		public new UseItemResult SetDelayCall(Action delayCall) { base.SetDelayCall(delayCall); return this; }
	    internal UseItemResult(int code, UseItemResultPOD result){
	        this.code = code;
	        this.result = result;
	    }
        public override MessageResult GetFutureResult(Task task) { return ((Task<UseItemResult>)task).Result; }
		public override int GetMessageId() {return NetMessageId.item_useItemResult;}
		public override SendPackage ToPackage() {
			SendPackage si_p = NetProtocolHelper.GetSendPackage();
			si_p.Header.Messagid = NetMessageId.item_useItemResult;
			si_p.StartWrite();
			SOutputStream _out = si_p.OutputStream;
			_out.Write_int(code);
			_out.Write_pod(result);
			return si_p;
		}
		public override string ToString() {
    		return "Item.SC_useItemResult { "
			+ "code="
			+ code
			+ ", result="
			+ result
			+" }";
		}
	}
	public class ExchangeResult : MessageResult {
	    private bool success;
	    private List<ItemShowPOD> showItems;
	    private Dictionary<int, int> exchangeRecords;
	    private float critMultiple;
	    public ExchangeResult(Task<ExchangeResult> future): base(future) { }
		public ExchangeResult(int code): base(code) { }
		public new ExchangeResult SetDelayCall(Action delayCall) { base.SetDelayCall(delayCall); return this; }
	    internal ExchangeResult(int code, bool success, List<ItemShowPOD> showItems, Dictionary<int, int> exchangeRecords, float critMultiple){
	        this.code = code;
	        this.success = success;
	        this.showItems = showItems == null ? null : new (showItems);
	        this.exchangeRecords = exchangeRecords == null ? null : new (exchangeRecords);
	        this.critMultiple = critMultiple;
	    }
        public override MessageResult GetFutureResult(Task task) { return ((Task<ExchangeResult>)task).Result; }
		public override int GetMessageId() {return NetMessageId.item_exchangeResult;}
		public override SendPackage ToPackage() {
			SendPackage si_p = NetProtocolHelper.GetSendPackage();
			si_p.Header.Messagid = NetMessageId.item_exchangeResult;
			si_p.StartWrite();
			SOutputStream _out = si_p.OutputStream;
			_out.Write_int(code);
			_out.Write_boolean(success);
			_out.Write_list_pod(showItems);
			_out.Write_map_int_int(exchangeRecords);
			_out.Write_float(critMultiple);
			return si_p;
		}
		public override string ToString() {
    		return "Item.SC_exchangeResult { "
			+ "code="
			+ code
			+ ", success="
			+ success
			+ ", showItems="
			+ showItems.ToString<ItemShowPOD>()
			+ ", exchangeRecords="
			+ exchangeRecords.ToString<int, int>()
			+ ", critMultiple="
			+ critMultiple
			+" }";
		}
	}
	public class ExchangeBatchResult : MessageResult {
	    private Dictionary<int, int> successInfo;
	    private List<ItemShowPOD> showItems;
	    private Dictionary<int, int> exchangeRecords;
	    public ExchangeBatchResult(Task<ExchangeBatchResult> future): base(future) { }
		public ExchangeBatchResult(int code): base(code) { }
		public new ExchangeBatchResult SetDelayCall(Action delayCall) { base.SetDelayCall(delayCall); return this; }
	    internal ExchangeBatchResult(int code, Dictionary<int, int> successInfo, List<ItemShowPOD> showItems, Dictionary<int, int> exchangeRecords){
	        this.code = code;
	        this.successInfo = successInfo == null ? null : new (successInfo);
	        this.showItems = showItems == null ? null : new (showItems);
	        this.exchangeRecords = exchangeRecords == null ? null : new (exchangeRecords);
	    }
        public override MessageResult GetFutureResult(Task task) { return ((Task<ExchangeBatchResult>)task).Result; }
		public override int GetMessageId() {return NetMessageId.item_exchangeBatchResult;}
		public override SendPackage ToPackage() {
			SendPackage si_p = NetProtocolHelper.GetSendPackage();
			si_p.Header.Messagid = NetMessageId.item_exchangeBatchResult;
			si_p.StartWrite();
			SOutputStream _out = si_p.OutputStream;
			_out.Write_int(code);
			_out.Write_map_int_int(successInfo);
			_out.Write_list_pod(showItems);
			_out.Write_map_int_int(exchangeRecords);
			return si_p;
		}
		public override string ToString() {
    		return "Item.SC_exchangeBatchResult { "
			+ "code="
			+ code
			+ ", successInfo="
			+ successInfo.ToString<int, int>()
			+ ", showItems="
			+ showItems.ToString<ItemShowPOD>()
			+ ", exchangeRecords="
			+ exchangeRecords.ToString<int, int>()
			+" }";
		}
	}
	public class SetPortableItemResult : MessageResult {
	    public SetPortableItemResult(Task<SetPortableItemResult> future): base(future) { }
		public SetPortableItemResult(int code): base(code) { }
		public new SetPortableItemResult SetDelayCall(Action delayCall) { base.SetDelayCall(delayCall); return this; }
        public override MessageResult GetFutureResult(Task task) { return ((Task<SetPortableItemResult>)task).Result; }
		public override int GetMessageId() {return NetMessageId.item_setPortableItemResult;}
		public override SendPackage ToPackage() {
			SendPackage si_p = NetProtocolHelper.GetSendPackage();
			si_p.Header.Messagid = NetMessageId.item_setPortableItemResult;
			si_p.StartWrite();
			SOutputStream _out = si_p.OutputStream;
			_out.Write_int(code);
			return si_p;
		}
		public override string ToString() {
    		return "Item.SC_setPortableItemResult { "
			+ "code="
			+ code
			+" }";
		}
	}
	public class NotifyItemChange : MessageNotify {
		private List<ItemPOD> updateList;
		public NotifyItemChange(List<ItemPOD> updateList) {
		    this.updateList = updateList == null ? null : new (updateList);
		}
		public override int GetMessageId() {return NetMessageId.item_notifyItemChange;}
		public override SendPackage ToPackage() {
			SendPackage si_p = NetProtocolHelper.GetSendPackage();
			si_p.Header.Messagid = NetMessageId.item_notifyItemChange;
			si_p.StartWrite();
			SOutputStream _out = si_p.OutputStream;
			_out.Write_list_pod(updateList);
			return si_p;
		}
		public override string ToString() {
			return "Item.SC_notifyItemChange { "
			+ "updateList="
			+ updateList.ToString<ItemPOD>()
			+" }";
		}
	}
	public class NotifyItemRemove : MessageNotify {
		private List<long> removeList;
		public NotifyItemRemove(List<long> removeList) {
		    this.removeList = removeList == null ? null : new (removeList);
		}
		public override int GetMessageId() {return NetMessageId.item_notifyItemRemove;}
		public override SendPackage ToPackage() {
			SendPackage si_p = NetProtocolHelper.GetSendPackage();
			si_p.Header.Messagid = NetMessageId.item_notifyItemRemove;
			si_p.StartWrite();
			SOutputStream _out = si_p.OutputStream;
			_out.Write_list_long(removeList);	
			return si_p;
		}
		public override string ToString() {
			return "Item.SC_notifyItemRemove { "
			+ "removeList="
			+ removeList.ToString<long>()
			+" }";
		}
	}
	public class NotifyBasicItemChange : MessageNotify {
		private Dictionary<int, int> updateList;
		public NotifyBasicItemChange(Dictionary<int, int> updateList) {
		    this.updateList = updateList == null ? null : new (updateList);
		}
		public override int GetMessageId() {return NetMessageId.item_notifyBasicItemChange;}
		public override SendPackage ToPackage() {
			SendPackage si_p = NetProtocolHelper.GetSendPackage();
			si_p.Header.Messagid = NetMessageId.item_notifyBasicItemChange;
			si_p.StartWrite();
			SOutputStream _out = si_p.OutputStream;
			_out.Write_map_int_int(updateList);
			return si_p;
		}
		public override string ToString() {
			return "Item.SC_notifyBasicItemChange { "
			+ "updateList="
			+ updateList.ToString<int, int>()
			+" }";
		}
	}
	public class NotifyItemDebts : MessageNotify {
		private Dictionary<int, int> itemDebts;
		public NotifyItemDebts(Dictionary<int, int> itemDebts) {
		    this.itemDebts = itemDebts == null ? null : new (itemDebts);
		}
		public override int GetMessageId() {return NetMessageId.item_notifyItemDebts;}
		public override SendPackage ToPackage() {
			SendPackage si_p = NetProtocolHelper.GetSendPackage();
			si_p.Header.Messagid = NetMessageId.item_notifyItemDebts;
			si_p.StartWrite();
			SOutputStream _out = si_p.OutputStream;
			_out.Write_map_int_int(itemDebts);
			return si_p;
		}
		public override string ToString() {
			return "Item.SC_notifyItemDebts { "
			+ "itemDebts="
			+ itemDebts.ToString<int, int>()
			+" }";
		}
	}
	public class NotifyItemCdInfo : MessageNotify {
		private Dictionary<int, int> itemCdInfo;
		public NotifyItemCdInfo(Dictionary<int, int> itemCdInfo) {
		    this.itemCdInfo = itemCdInfo == null ? null : new (itemCdInfo);
		}
		public override int GetMessageId() {return NetMessageId.item_notifyItemCdInfo;}
		public override SendPackage ToPackage() {
			SendPackage si_p = NetProtocolHelper.GetSendPackage();
			si_p.Header.Messagid = NetMessageId.item_notifyItemCdInfo;
			si_p.StartWrite();
			SOutputStream _out = si_p.OutputStream;
			_out.Write_map_int_int(itemCdInfo);
			return si_p;
		}
		public override string ToString() {
			return "Item.SC_notifyItemCdInfo { "
			+ "itemCdInfo="
			+ itemCdInfo.ToString<int, int>()
			+" }";
		}
	}
	public class NotifyUpdatePortableItem : MessageNotify {
		private long itemId;
		public NotifyUpdatePortableItem(long itemId) {
		    this.itemId = itemId;
		}
		public override int GetMessageId() {return NetMessageId.item_notifyUpdatePortableItem;}
		public override SendPackage ToPackage() {
			SendPackage si_p = NetProtocolHelper.GetSendPackage();
			si_p.Header.Messagid = NetMessageId.item_notifyUpdatePortableItem;
			si_p.StartWrite();
			SOutputStream _out = si_p.OutputStream;
			_out.Write_long(itemId);
			return si_p;
		}
		public override string ToString() {
			return "Item.SC_notifyUpdatePortableItem { "
			+ "itemId="
			+ itemId
			+" }";
		}
	}
	private class SellItemRequest : IReceiveMessage
    {
		internal List<long> itemIds;
		internal Dictionary<int, int> basicItems;
        public void FromPackage(ReceivePackage package)
		{
			SInputStream _in = package.InputStream;
            itemIds = _in.HasRemaining() ? _in.Read_list_long() : default;
            basicItems = _in.HasRemaining() ? _in.Read_map_int_int() : default;
		}
        public int GetMessageId() { return NetMessageId.item_sellItem; }
        public override string ToString()
        {
            return "Item.sellItem"+ ", itemIds="+ itemIds.ToString<long>()+ ", basicItems="+ basicItems.ToString<int, int>();
        }
    }
	private class UseItemRequest : IReceiveMessage
    {
		internal UseItemRequestPOD request;
        public void FromPackage(ReceivePackage package)
		{
			SInputStream _in = package.InputStream;
            request = _in.HasRemaining() ? _in.Read_pod<UseItemRequestPOD>(UseItemRequestPOD.DynamicFactory) : default;
		}
        public int GetMessageId() { return NetMessageId.item_useItem; }
        public override string ToString()
        {
            return "Item.useItem"+ ", request="+ request;
        }
    }
	private class ExchangeRequest : IReceiveMessage
    {
		internal int cid;
		internal int count;
        public void FromPackage(ReceivePackage package)
		{
			SInputStream _in = package.InputStream;
            cid = _in.HasRemaining() ? _in.Read_int() : default;
            count = _in.HasRemaining() ? _in.Read_int() : default;
		}
        public int GetMessageId() { return NetMessageId.item_exchange; }
        public override string ToString()
        {
            return "Item.exchange"+ ", cid="+ cid+ ", count="+ count;
        }
    }
	private class ExchangeBatchRequest : IReceiveMessage
    {
		internal Dictionary<int, int> idCounts;
        public void FromPackage(ReceivePackage package)
		{
			SInputStream _in = package.InputStream;
            idCounts = _in.HasRemaining() ? _in.Read_map_int_int() : default;
		}
        public int GetMessageId() { return NetMessageId.item_exchangeBatch; }
        public override string ToString()
        {
            return "Item.exchangeBatch"+ ", idCounts="+ idCounts.ToString<int, int>();
        }
    }
	private class SetPortableItemRequest : IReceiveMessage
    {
		internal long itemId;
        public void FromPackage(ReceivePackage package)
		{
			SInputStream _in = package.InputStream;
            itemId = _in.HasRemaining() ? _in.Read_long() : default;
		}
        public int GetMessageId() { return NetMessageId.item_setPortableItem; }
        public override string ToString()
        {
            return "Item.setPortableItem"+ ", itemId="+ itemId;
        }
    }
	}
#endregion
}